#include "CameraSceneNode.h"

namespace ISNW
{
namespace scene
{
	CameraSceneNode::CameraSceneNode(
		ISceneManager*sm,
		ISceneNode* parent,
		s32 id,
		core::vector3df pos, 
		core::vector3df t,
		core::vector3df up)
		:ICameraSceneNode(sm,parent,id,pos,t,up),target(t),upvec(up)
	{

	}
	void CameraSceneNode::setProjectiveMatirx(core::matrix4f projMatrix)
	{
		viewArea.Matrices[PROJECTIVE_MATRIX] = projMatrix;
		viewArea.setTransform(PROJECTIVE_MATRIX);
	}

	core::matrix4f CameraSceneNode::getProjectiveMatrix() const
	{
		return viewArea.Matrices[PROJECTIVE_MATRIX];
	}

	void CameraSceneNode::setViewMatrix(core::matrix4f viewMatrix)
	{
		viewArea.Matrices[VIEW_MATRIX] = viewMatrix;
		viewArea.setTransform(VIEW_MATRIX);
	}

	core::matrix4f CameraSceneNode::getViewMatrix() const
	{
		return viewArea.Matrices[VIEW_MATRIX];
	}

	void CameraSceneNode::setTarget(core::vector3df t)
	{
		target = t;
	}

	core::vector3df CameraSceneNode::getTarget() const
	{
		return target;
	}

	void CameraSceneNode::setFov(f32 angle)
	{
		fov = angle;
	}

	f32 CameraSceneNode::getFov() const
	{
		return fov;
	}

	void CameraSceneNode::setUpVec(core::vector3df upVec)
	{
		upvec = upVec;
	}

	core::vector3df CameraSceneNode::getUpVec() const
	{
		return upvec;
	}

	void CameraSceneNode::setNear(f32 n)
	{
		Near = n;
	}

	f32 CameraSceneNode::getNear() const
	{
		return Near;
	}

	void CameraSceneNode::setFar(f32 f)
	{
		Far = f;
	}

	f32 CameraSceneNode::getFar() const
	{
		return Far;
	}

	void CameraSceneNode::setAspectRadio(f32 a)
	{
		aspect = a;
	}

	f32 CameraSceneNode::getAspectRadio() const
	{
		return aspect;
	}

	const Frustum& CameraSceneNode::getFrustum() const
	{
		return viewArea;
	}

	void CameraSceneNode::recalculateProjectiveMatrix()
	{
		viewArea.Matrices[PROJECTIVE_MATRIX].buildProjectionMatrixPerspectiveFovLH(fov,aspect,Near,Far);
		viewArea.setTransform(PROJECTIVE_MATRIX);
	}

	void CameraSceneNode::recalculateViewMatrix()
	{
		core::vector3df pos = getAbsolutePosition();
		viewArea.Matrices[VIEW_MATRIX].buildCameraLookAtMatrixLH(pos,target,upvec);
		viewArea.setTransform(VIEW_MATRIX);
	}

	void CameraSceneNode::recalculateViewArea()
	{
		viewArea.Near = Near;
		viewArea.Far = Far;
		viewArea.setplane(viewArea.Matrices[PROJVIEW_MATRIX]);
	}

	void CameraSceneNode::onRegisterSceneNode()
	{
		recalculateViewMatrix();
		recalculateProjectiveMatrix();
		recalculateViewArea();

		scenemanager->registernodeforrendering(this,E_RT_CAMERA);
		ISceneNode::onRegisterSceneNode();
	}

	void CameraSceneNode::render()
	{
		if(isVisible)
		{
			video::IDriver* driver = scenemanager->getdriver();

			if(!driver) return;

			driver->setTransform(video::E_PROJECTIVE,viewArea.Matrices[PROJECTIVE_MATRIX]);
			driver->setTransform(video::E_VIEW,viewArea.Matrices[VIEW_MATRIX]);
		}
	}

} // end namespace scene
} // end namespace ISNW